using Circus.CodeEditor;
using Circus.CodeEditor.Serialization;
using Circus.CodeEditor.TextSource;
using Circus.Syntax;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using System.Windows.Forms;
namespace Circus.CodeEditor
{
	public class Selection2 : IDisposable
	{
		internal class UndoComparer : IComparer<TextUndo>
		{
			public int Compare(TextUndo x, TextUndo y)
			{
				int num = x.Start - y.Start;
				if (num == 0)
				{
					num = ((x.Text != null) ? 0 : 1) - ((y.Text != null) ? 0 : 1);
				}
				return num;
			}
		}
		public CodeEditor owner;
		public SelectionType selectionType;
		public Rectangle selectionRect;
		public SelectionOptions options = EditConsts.DefaultSelectionOptions;
		public AllowedSelectionMode allowedSelectionMode = EditConsts.DefaultSelectionMode;
		public Color foreColor = EditConsts.DefaultHighlightForeColor;
		public Color backColor = EditConsts.DefaultHighlightBackColor;
		public Color inActiveForeColor = EditConsts.DefaultInactiveHighlightForeColor;
		public Color inActiveBackColor = EditConsts.DefaultInactiveHighlightBackColor;
		public Color borderColor = EditConsts.DefaultSelectionBorderColor;
		public int updateCount;
		public bool atTopLeftEnd;
		public bool atBottomRightEnd;
		public Rectangle oldSelectionRect = Rectangle.Empty;
		public SelectionType oldSelectionType = SelectionType.None;
		public Point oldPos = Point.Empty;
		public SelectionState selectionState;
		public Point selStart = Point.Empty;
		public Point selEnd = Point.Empty;
		public bool selForward;
		public Timer selTimer;
		public KeyEvent moveSelection;
		public TextUndoEvent tabifyLineEvent;
		public TextUndoEvent unTabifyLineEvent;
		public TextUndoEvent indentLineEvent;
		public TextUndoEvent unIndentLineEvent;
		public TextUndoEvent lowerCaseLineEvent;
		public TextUndoEvent upperCaseLineEvent;
		public TextUndoEvent capitalizeLineEvent;
		public TextUndoEvent deleteWhiteSpaceEvent;
		public TextUndoEvent commentLineEvent;
		public TextUndoEvent uncommentLineEvent;
		public TextUndoEventEx commentMultiLineEvent;
		public TextUndoEventEx uncommentMultiLineEvent;
		public IComparer<TextUndo> undoComparer;

	    [Browsable(false)]
	    public event EventHandler SelectionChanged;
		protected EventHandlers KeyHandlers
		{
			get
			{
				return this.owner.KeyList.Handlers as EventHandlers;
			}
		}
		[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public virtual int UpdateCount
		{
			get
			{
				return this.updateCount;
			}
		}
		[Browsable(false)]
		public virtual bool IsEmpty
		{
			get
			{
				return this.selectionType == SelectionType.None;
			}
		}
		[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public virtual int SelectionStart
		{
			get
			{
				return this.owner.Source.TextPointToAbsolutePosition(this.GetSelectionPoint());
			}
			set
			{
				this.selectionType = SelectionType.None;
				this.owner.Source.MoveTo(this.owner.Source.AbsolutePositionToTextPoint(value));
			}
		}
		[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public virtual int SelectionLength
		{
			get
			{
				return this.SelectedText.Length;
			}
			set
			{
				this.SetSelection(SelectionType.Stream, this.GetSelectionPoint(), this.owner.Source.AbsolutePositionToTextPoint(this.SelectionStart + value));
			}
		}
		[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public virtual Rectangle SelectionRect
		{
			get
			{
				return this.selectionRect;
			}
			set
			{
				this.SetSelection(this.selectionType, value);
			}
		}
		[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public virtual SelectionType SelectionType
		{
			get
			{
				return this.selectionType;
			}
			set
			{
				this.SetSelection(value, this.selectionRect);
			}
		}
		[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public virtual string SelectedText
		{
			get
			{
				return this.GetSelectedText(false);
			}
			set
			{
				this.SetSelectedText(value, SelectionType.Stream);
			}
		}
		[Description("Gets or sets options determining behaviour or the \"Selection\"."), Editor("QWhale.Design.FlagEnumerationEditor, QWhale.Design", typeof(UITypeEditor))]
		public virtual SelectionOptions Options
		{
			get
			{
				return this.options;
			}
			set
			{
				if (this.options != value)
				{
					this.options = value;
					this.OnOptionsChanged();
				}
			}
		}
		[Description("Gets or sets a foreground color of the \"SelectedText\" when owner control has input focus.")]
		public virtual Color ForeColor
		{
			get
			{
				return this.foreColor;
			}
			set
			{
				if (this.foreColor != value)
				{
					this.foreColor = value;
					this.OnForeColorChanged();
				}
			}
		}

	    [Description("Gets or sets a foreground color of the \"SelectedText\" when owner control does not have input focus.")]
		public virtual Color InActiveForeColor
		{
			get
			{
				return this.inActiveForeColor;
			}
			set
			{
				if (this.inActiveForeColor != value)
				{
					this.inActiveForeColor = value;
					this.OnInActiveForeColorChanged();
				}
			}
		}

	    [Description("Gets or sets type of selection allowed to Edit control content."), Editor("QWhale.Design.FlagEnumerationEditor, QWhale.Design", typeof(UITypeEditor))]
		public virtual AllowedSelectionMode AllowedSelectionMode
		{
			get
			{
				return this.allowedSelectionMode;
			}
			set
			{
				if (this.allowedSelectionMode != value)
				{
					this.allowedSelectionMode = value;
					this.OnAllowedSelectionModeChanged();
				}
			}
		}
		[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public virtual SelectionState SelectionState
		{
			get
			{
				return this.selectionState;
			}
			set
			{
				if (this.selectionState != value)
				{
					this.selectionState = value;
					this.OnSelectionStateChanged();
				}
			}
		}
		[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public virtual string SelectedColorData
		{
			get
			{
				string result;
				if (this.IsEmpty)
				{
					result = string.Empty;
				}
				else
				{
					StringBuilder stringBuilder = new StringBuilder();
					bool flag = true;
					for (int i = 0; i < this.SelectedCount(); i++)
					{
						string text = this.SelectedData(i);
						if (text != null)
						{
							if (!flag)
							{
								stringBuilder.Append(new string('\0', this.owner.LineTerminator.Length));
							}
							stringBuilder.Append(text);
							flag = false;
						}
					}
					result = stringBuilder.ToString();
				}
				return result;
			}
		}
		 
		public void SwapMaxInt(ref int left, ref int right)
		{
			if (right < left)
			{
				int num = left;
				left = right;
				right = num;
			}
		}
		public void SwapRect(ref Rectangle rect)
		{
			Point location = rect.Location;
			Point location2 = rect.Location + rect.Size;
			rect.Location = location2;
			rect.Width = location.X - rect.X;
			rect.Height = location.Y - rect.Y;
		}
		public void CheckSelectionMode(ref SelectionType selType)
		{
			if (this.allowedSelectionMode == AllowedSelectionMode.None)
			{
				selType = SelectionType.None;
			}
			else
			{
				switch (selType)
				{
				case SelectionType.Stream:
					if ((this.allowedSelectionMode & AllowedSelectionMode.Stream) == AllowedSelectionMode.None)
					{
						selType = SelectionType.Block;
					}
					break;
				case SelectionType.Block:
					if ((this.allowedSelectionMode & AllowedSelectionMode.Block) == AllowedSelectionMode.None)
					{
						selType = SelectionType.Stream;
					}
					break;
				}
			}
		}
		public void SelectBlock(SelectionType selType, SelectionType newSelType, Point position, KeyEvent action)
		{
			Rectangle rectangle = this.SelectionRect;
			int x = position.X;
			int y = position.Y;
			int num = y;
			if (newSelType == SelectionType.Block && !false)
			{
				newSelType = SelectionType.Stream;
			}
			this.CheckSelectionMode(ref newSelType);
			this.BeginUpdate();
			try
			{
				DisplayStrings displayLines = this.owner.DisplayLines;
				if (selType == SelectionType.None || !this.IsValidSelectionPoint(position))
				{
					rectangle.X = position.X;
					rectangle.Y = position.Y;
					rectangle.Width = 0;
					rectangle.Height = 0;
				}
				Point point = displayLines.PointToDisplayPoint(x, y);
				if (action != null)
				{
					if (newSelType == SelectionType.Block && !this.owner.WordWrap)
					{
                        Circus.CodeEditor.TextSource.TextSource source = this.owner.Source;
						NavigateOptions navigateOptions = source.NavigateOptions;
						try
						{
							source.SetNavigateOptions(navigateOptions | NavigateOptions.BeyondEol);
							action();
						}
						finally
						{
							source.SetNavigateOptions(navigateOptions);
						}
					}
					else
					{
						action();
					}
				}
				Point position2 = this.owner.Position;
				if (num >= this.owner.Lines.Count)
				{
                    Circus.CodeEditor.TextSource.TextSource source = this.owner.Source;
					NavigateOptions navigateOptions = source.NavigateOptions;
					try
					{
						source.SetNavigateOptions(navigateOptions & ~NavigateOptions.BeyondEof);
						source.ValidatePosition(ref position2);
					}
					finally
					{
						source.SetNavigateOptions(navigateOptions);
					}
				}
				if (newSelType == SelectionType.Block)
				{
					position2 = displayLines.PointToDisplayPoint(position2);
					if (position2.X < point.X)
					{
						int num2 = point.X;
						point.X = position2.X;
						position2.X = num2;
					}
					if (position2.Y < point.Y)
					{
						int num2 = point.Y;
						point.Y = position2.Y;
						position2.Y = num2;
					}
					point = displayLines.DisplayPointToPoint(point.X, point.Y, true, false, false);
					position2 = displayLines.DisplayPointToPoint(position2.X, position2.Y, true, false, false);
					rectangle = new Rectangle(point.X, point.Y, position2.X - point.X, position2.Y - point.Y);
				}
				else
				{
					rectangle = new Rectangle(x, y, position2.X - x, position2.Y - y);
					if (rectangle.Height < 0 || (rectangle.Width < 0 && rectangle.Height == 0))
					{
						this.SwapRect(ref rectangle);
					}
				}
				if (this.owner.Source.UpdateCount == 0 && !this.IsEmpty)
				{
					Region selectionRegion = this.GetSelectionRegion(this.SelectionType, this.SelectionRect);
					if (selectionRegion != null)
					{
						this.owner.Invalidate(selectionRegion);
						selectionRegion.Dispose();
					}
				}
				if (newSelType != SelectionType.None)
				{
					if (rectangle.Location == this.owner.Position)
					{
						this.atTopLeftEnd = displayLines.LineEnd;
					}
					if (this.owner.Position == new Point(rectangle.Right, rectangle.Bottom))
					{
						this.atBottomRightEnd = displayLines.LineEnd;
					}
				}
				this.SetSelection(newSelType, rectangle);
			}
			finally
			{
				this.EndUpdate();
			}
		}
		public void SelectBlock(SelectionType newSelType, KeyEvent action)
		{
			this.UpdateSelStart(true);
			this.SelectBlock(this.selectionType, newSelType, this.selStart, action);
		}
		public Point GetSelectionPoint()
		{
			Point result;
			if (!this.IsEmpty)
			{
				result = this.selectionRect.Location;
			}
			else
			{
				result = this.owner.Position;
			}
			return result;
		}
		public Point UpdateWordSelectionEnd(Point pt)
		{
			Point result = pt;
			int num = 0;
			int num2 = 0;
			if ((SelectionOptions.WordSelect & this.Options) != SelectionOptions.None)
			{
				if (this.owner.Lines.GetWord(pt.Y, pt.X, out num, out num2) && (pt.Y != this.selStart.Y || this.selStart.X < num || this.selStart.X > num2))
				{
					result.X = ((pt.Y > this.selStart.Y || (pt.Y == this.selStart.Y && pt.X >= this.selStart.X)) ? (num2 + 1) : num);
				}
			}
			return result;
		}
		public void UpdateWordSelection(ref Point pt, bool direction)
		{
			if (this.selectionState == SelectionState.SelectWord)
			{
				if (this.selectionType == SelectionType.Block)
				{
                    Circus.CodeEditor.TextSource.TextSource source = this.owner.Source;
					NavigateOptions navigateOptions = source.NavigateOptions;
					try
					{
						source.SetNavigateOptions(navigateOptions | NavigateOptions.BeyondEol);
						source.ValidatePosition(ref pt);
					}
					finally
					{
						source.SetNavigateOptions(navigateOptions);
					}
				}
				else
				{
					this.owner.Source.ValidatePosition(ref pt);
				}
				int num;
				int num2;
				if (this.owner.Lines.GetWord(pt.Y, pt.X, out num, out num2))
				{
					pt.X = (direction ? (num2 + 1) : num);
				}
			}
		}
		public void MoveSelection()
		{
			Point position = this.UpdateWordSelectionEnd(this.selEnd);
			this.UpdateWordSelection(ref position, this.selForward);
			if (this.selectionType == SelectionType.Block)
			{
                Circus.CodeEditor.TextSource.TextSource source = this.owner.Source;
				NavigateOptions navigateOptions = source.NavigateOptions;
				try
				{
					source.SetNavigateOptions(navigateOptions | NavigateOptions.BeyondEol);
					this.owner.Position = position;
				}
				finally
				{
					source.SetNavigateOptions(navigateOptions);
				}
			}
			else
			{
				this.owner.Position = position;
			}
		}
		public void TabifyLine(string str, TextUndoList operations)
		{
			int i = 0;
			TextStrings lines = this.owner.Lines;
			int length = str.Length;
			while (i < length)
			{
				if (str[i] == ' ')
				{
					int num = i;
					while (num + 1 < str.Length && str[num + 1] == ' ')
					{
						num++;
					}
					operations.Add(new TextUndo(i, num - i + 1, lines.GetIndentString(num - i + 1, this.owner.Lines.TabPosToPos(str, i), false)));
					i = num;
				}
				i++;
			}
		}
		public void UnTabifyLine(string str, TextUndoList operations)
		{
			this.owner.Lines.GetTabString(str, operations);
		}
		public void IndentLine(string str, TextUndoList operations)
		{
			TextStrings lines = this.owner.Lines;
			operations.Add(new TextUndo(0, 0, lines.UseSpaces ? new string(' ', lines.GetTabStop(0)) : "\t"));
		}
		public void UnIndentLine(string str, TextUndoList operations)
		{
			if (str != string.Empty)
			{
				TextStrings lines = this.owner.Lines;
				int num = lines.UseSpaces ? lines.GetTabStop(0) : 1;
				string text = str.Substring(0, Math.Min(num, str.Length));
				num = text.Length;
				num -= text.TrimStart(null).Length;
				if (num > 0)
				{
					operations.Add(new TextUndo(0, num, string.Empty));
				}
			}
		}
		public void LowerCaseLine(string str, TextUndoList operations)
		{
			operations.Add(new TextUndo(0, str.Length, str.ToLower()));
		}
		public void UpperCaseLine(string str, TextUndoList operations)
		{
			operations.Add(new TextUndo(0, str.Length, str.ToUpper()));
		}
		public void CapitalizeLine(string str, TextUndoList operations)
		{
			char[] array = str.ToLower().ToCharArray();
			TextStrings lines = this.owner.Lines;
			for (int i = 0; i < array.Length; i++)
			{
				bool flag = !lines.IsDelimiter(array[i]);
				if (i != 0)
				{
					flag = (flag && lines.IsDelimiter(array[i - 1]));
				}
				if (flag)
				{
					operations.Add(new TextUndo(i, 1, char.ToUpper(array[i]).ToString()));
				}
			}
		}
		public int IndexOfNonWhitespaceChar(string s)
		{
			int length = s.Length;
			TextStrings lines = this.owner.Lines;
			int result;
			for (int i = 0; i < length; i++)
			{
				if (!lines.IsWhitespace(s, i))
				{
					result = i;
					return result;
				}
			}
			result = -1;
			return result;
		}
		public void DeleteWhiteSpace(string str, TextUndoList operations)
		{
			int i = 0;
			int length = str.Length;
			while (i < length)
			{
				if (str[i] == ' ' || str[i] == '\t')
				{
					int num = i;
					while (num < length - 1 && (str[num + 1] == ' ' || str[num + 1] == '\t'))
					{
						num++;
					}
					operations.Add(new TextUndo(i, num - i + 1, string.Empty));
					i = num;
				}
				i++;
			}
		}
		public void CommentLine(string str, TextUndoList operations)
		{
			if (this.owner.Lexer is SyntaxParser)
			{
				string singleLineComment = ((SyntaxParser)this.owner.Lexer).GetSingleLineComment();
				if (singleLineComment != string.Empty)
				{
					operations.Add(new TextUndo(0, 0, singleLineComment));
				}
			}
		}
		public void CommentMultiLine(Range range, int index, string str, TextUndoList operations)
		{
			if (index == range.StartPoint.Y || index == range.EndPoint.Y)
			{
				string text;
				string text2;
				if (this.owner.Lexer is SyntaxParser && ((SyntaxParser)this.owner.Lexer).GetMultiLineComment(out text, out text2))
				{
					if (index == range.StartPoint.Y)
					{
						int num = str.Length - str.TrimStart(new char[0]).Length;
						operations.Add(new TextUndo(num, 0, text));
						range.StartPoint = new Point(num, range.StartPoint.Y);
					}
					if (index == range.EndPoint.Y)
					{
						int num = str.TrimEnd(new char[0]).Length;
						operations.Add(new TextUndo(num, 0, text2));
						num += text2.Length;
						if (range.StartPoint.Y == range.EndPoint.Y)
						{
							num += text.Length;
						}
						range.EndPoint = new Point(num, range.EndPoint.Y);
					}
				}
			}
		}
		public void UncommentMultiLine(Range range, int index, string str, TextUndoList operations)
		{
			if (index == range.StartPoint.Y || index == range.EndPoint.Y)
			{
				string text;
				string text2;
				if (this.owner.Lexer is SyntaxParser && ((SyntaxParser)this.owner.Lexer).GetMultiLineComment(out text, out text2))
				{
					if (index == range.StartPoint.Y)
					{
						int num = str.IndexOf(text);
						int num2 = str.Length - str.TrimStart(new char[0]).Length;
						if (num >= 0 && num <= num2)
						{
							operations.Add(new TextUndo(num, text.Length, string.Empty));
						}
						range.StartPoint = new Point(num2, range.StartPoint.Y);
					}
					if (index == range.EndPoint.Y)
					{
						int num = str.LastIndexOf(text2);
						int num2 = str.Length - str.TrimEnd(new char[0]).Length;
						if (num >= num2)
						{
							operations.Add(new TextUndo(num, text2.Length, string.Empty));
						}
						num2 -= text2.Length;
						if (range.StartPoint.Y == range.EndPoint.Y)
						{
							num2 -= text.Length;
						}
						range.EndPoint = new Point(Math.Max(str.Length - num2, 0), range.EndPoint.Y);
					}
				}
			}
		}
		public void UncommentLine(string str, TextUndoList operations)
		{
			if (this.owner.Lexer is SyntaxParser)
			{
				string singleLineComment = ((SyntaxParser)this.owner.Lexer).GetSingleLineComment();
				if (singleLineComment != string.Empty)
				{
					int num = str.IndexOf(singleLineComment);
					if (num >= 0 && num <= str.Length - str.TrimStart(new char[0]).Length)
					{
						operations.Add(new TextUndo(num, singleLineComment.Length, string.Empty));
					}
				}
			}
		}
		public Region GetSelectionRegion(SelectionType selectionType, Rectangle rect)
		{
			return this.owner.SyntaxPaint.GetRectRegion(selectionType, rect, this.atTopLeftEnd, this.atBottomRightEnd);
		}
		public string SafeSubString(string s, int left, int right)
		{
			string result;
			if (left < s.Length)
			{
				if (right < s.Length)
				{
					result = s.Substring(left, right - left);
				}
				else
				{
					result = s.Substring(left);
				}
			}
			else
			{
				result = string.Empty;
			}
			return result;
		}
		public string SafeSubString(StringItemInfo[] data, int left, int right)
		{
			string result;
			if (left < data.Length)
			{
				char[] array = new char[Math.Min(right, data.Length) - left];
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = (char)data[i + left].Data;
				}
				result = new string(array);
			}
			else
			{
				result = string.Empty;
			}
			return result;
		}
		public int GetSelectedBounds(int index, IList<Range> list)
		{
			return this.GetSelectedBounds(index, list, this.selectionType, this.selectionRect);
		}
		public int GetSelectedBounds(int index, IList<Range> list, SelectionType selType, Rectangle selRect)
		{
			switch (selType)
			{
			case SelectionType.Stream:
				if (index <= this.selectionRect.Bottom && index >= this.selectionRect.Top)
				{
					int num;
					int num2;
					if (index == this.selectionRect.Top)
					{
						if (index == this.selectionRect.Bottom)
						{
							num = this.selectionRect.Left;
							num2 = this.selectionRect.Right;
						}
						else
						{
							num = this.selectionRect.Left;
							num2 = int.MaxValue;
						}
					}
					else
					{
						if (index == this.selectionRect.Bottom)
						{
							num = 0;
							num2 = this.selectionRect.Right;
						}
						else
						{
							num = 0;
							num2 = int.MaxValue;
						}
					}
					list.Add(new Range(num, index, num2, index));
				}
				break;
			case SelectionType.Block:
			{
				DisplayStrings displayLines = this.owner.DisplayLines;
				for (int i = displayLines.PointToDisplayPoint(0, index).Y; i <= displayLines.PointToDisplayPoint(this.owner.Lines.GetLength(index), index).Y; i++)
				{
					int num;
					int num2;
					if (this.GetSelectionForLine(i, out num, out num2, false, selType, selRect))
					{
						Point point = displayLines.DisplayPointToPoint(num, i);
						Point point2 = displayLines.DisplayPointToPoint(num2, i, false, false, true);
						if (index >= point.Y && index <= point2.Y)
						{
							if (index == point.Y)
							{
								if (index == point2.Y)
								{
									num = point.X;
									num2 = point2.X;
								}
								else
								{
									num = point.X;
									num2 = int.MaxValue;
								}
							}
							else
							{
								if (index == point2.Y)
								{
									num = 0;
									num2 = point2.X;
								}
								else
								{
									num = 0;
									num2 = int.MaxValue;
								}
							}
							list.Add(new Range(num, index, num2, index));
						}
					}
				}
				break;
			}
			}
			return list.Count;
		}
		public int DoInsertString(SelectionType selType, string s, bool insertLine)
		{
			if (insertLine)
			{
				if (selType == SelectionType.Block)
				{
					if (this.owner.Position.Y < this.owner.DisplayLines.DisplayCount - 1)
					{
						this.owner.MoveLineDown();
					}
					else
					{
						this.owner.Source.NewLineBelow();
					}
				}
				else
				{
					this.owner.Source.BreakLine();
					this.owner.MoveTo(0, this.owner.Position.Y + 1);
				}
			}
			this.owner.Source.Insert(s);
			return s.Length;
		}
		public int GetTabIndent(int indent)
		{
			return this.owner.Lines.TabPosToPos(new string('\t', indent), indent);
		}
		protected string GetSelectedText(bool singleLine)
		{
			string result;
			if (this.IsEmpty)
			{
				result = string.Empty;
			}
			else
			{
				StringBuilder stringBuilder = new StringBuilder();
				bool flag = true;
				for (int i = 0; i < this.SelectedCount(); i++)
				{
					string text = this.SelectedString(i);
					if (text != null)
					{
						if (!flag)
						{
							stringBuilder.Append(this.owner.LineTerminator);
						}
						stringBuilder.Append(text);
						flag = false;
					}
				}
				string text2 = stringBuilder.ToString();
				if (this.SelectedCount() - 1 == 1 && singleLine)
				{
					text2 = text2.Replace("\r\n", '\r'.ToString());
				}
				result = text2;
			}
			return result;
		}
		protected void WriteToClipboard(bool singleLine)
		{
			DataObject dataObject = new DataObject();
			string text = this.GetSelectedText(singleLine);
			if (text != string.Empty)
			{
				dataObject.SetText(text);
				if ((this.options & SelectionOptions.RtfClipboard) != SelectionOptions.None)
				{
					TextStrings textStrings = new TextStrings(null);
					textStrings.Owner = this.owner;
					textStrings.SetTextAndData(text, this.owner.Source.NeedParse() ? this.SelectedColorData : null);
					StringWriter stringWriter = new StringWriter();
					try
					{

                        // todo
                        //textStrings.SaveStream(stringWriter, new RtfExport());
						text = stringWriter.ToString();
						if (text != string.Empty)
						{
							dataObject.SetText(text, TextDataFormat.Rtf);
						}
					}
					finally
					{
						stringWriter.Close();
					}
				}
			}
			else
			{
				dataObject.SetData(text);
			}
			if (this.SelectionType != SelectionType.None)
			{
				dataObject.SetData(DataFormats.Serializable, this.SelectionType);
			}
			try
			{
				try
				{
					Clipboard.SetDataObject(dataObject, true);
				}
				catch
				{
					Clipboard.SetDataObject(dataObject);
				}
			}
			catch
			{
			}
		}
		protected bool CanSelectBlock()
		{
			return (Control.ModifierKeys & Keys.Alt) != Keys.None;
		}
		protected void UpdateSelRect(ref SelectionType oldSelectionType, SelectionType newSelectionType, ref Rectangle oldRect, Rectangle newRect, ref bool changed)
		{
			changed = false;
			if (oldSelectionType != newSelectionType || oldRect != newRect)
			{
				bool flag = this.owner.Source.UpdateCount == 0;
				Region region = flag ? this.GetSelectionRegion(oldSelectionType, oldRect) : null;
				if ((SelectionOptions.DisableSelection & this.options) != SelectionOptions.None)
				{
					newSelectionType = SelectionType.None;
				}
				else
				{
					if (this.IsSelectionRectEmpty(newSelectionType, newRect))
					{
						newSelectionType = SelectionType.None;
					}
				}
				if (newSelectionType == SelectionType.None)
				{
					newRect = Rectangle.Empty;
					this.atTopLeftEnd = false;
					this.atBottomRightEnd = false;
				}
				changed = true;
				oldRect = newRect;
				oldSelectionType = newSelectionType;
				if (flag)
				{
					Region selectionRegion = this.GetSelectionRegion(newSelectionType, newRect);
					if (region == null)
					{
						region = selectionRegion;
					}
					else
					{
						if (selectionRegion != null)
						{
							region.Union(selectionRegion);
							selectionRegion.Dispose();
						}
					}
					if (region != null)
					{
						this.owner.Invalidate(region, false);
						region.Dispose();
					}
				}
			}
		}
		protected void UndoOperations(TextUndoList operations, bool withUndo)
		{
            Circus.CodeEditor.TextSource.TextSource source = this.owner.Source;
			source.BeginUpdate(UpdateReason.Other);
			try
			{
				for (int i = operations.Count - 1; i >= 0; i--)
				{
					TextUndo textUndo = operations[i];
					source.MoveTo(textUndo.StartPt);
					this.SetSelection(SelectionType.Stream, textUndo.StartPt, textUndo.EndPt);
					this.SetSelectedText(textUndo.Text, SelectionType.Stream);
				}
			}
			finally
			{
				source.EndUpdate();
			}
		}
		protected int UndoOperations(int line, TextUndoList operations, bool withUndo)
		{
			int num = 0;
			operations.Sort(this.undoComparer);
            Circus.CodeEditor.TextSource.TextSource source = this.owner.Source;
			for (int i = operations.Count - 1; i >= 0; i--)
			{
				TextUndo textUndo = operations[i];
				bool flag = textUndo.Text.Length == textUndo.Len;
				if (flag)
				{
					source.DisablePositionUpdate();
				}
				int index = withUndo ? source.StorePositionWithUndo(source.Position) : source.StorePosition(source.Position);
				try
				{
					if (textUndo.Len > 0)
					{
						source.MoveTo(textUndo.Start, line);
						source.DeleteRight(textUndo.Len);
					}
					if (textUndo.Text != string.Empty)
					{
						source.MoveTo(textUndo.Start, line);
						source.Insert(textUndo.Text);
					}
					num += textUndo.Text.Length - textUndo.Len;
				}
				finally
				{
					if (withUndo)
					{
						source.RestorePositionWithUndo(index);
					}
					else
					{
						source.Position = source.RestorePosition(index);
					}
					if (flag)
					{
						source.EnablePositionUpdate();
					}
				}
			}
			return num;
		}
		protected void SmartFormat(bool needFormat, bool notify, bool needIndent, int line)
		{
			if (this.owner.Source.NeedFormatText())
			{
				this.BeginUpdate();
				try
				{
					bool isEmpty = this.IsEmpty;
					if (isEmpty)
					{
						this.SetSelection(SelectionType.Stream, new Rectangle(0, line, Math.Max(this.owner.Lines[line].Length, 1), 0));
					}
					if (!this.IsEmpty)
					{
						int num = 0;
						int index = 0;
						int index2 = 0;
                        Circus.CodeEditor.TextSource.TextSource source = this.owner.Source;
						source.BeginUpdate(UpdateReason.InsertBlock);
						source.State |= NotifyState.SmartFormat;
						try
						{
							SyntaxParser syntaxParser = (SyntaxParser)this.owner.Source.Lexer;
							TextUndoList textUndoList = new TextUndoList();
							syntaxParser.Prepare(source.FileName, source.Lines, null, false);
							Point location = this.selectionRect.Location;
							Point position = new Point(this.selectionRect.Right, this.selectionRect.Bottom);
							if (syntaxParser.SmartFormat(ref location, ref position, source.Lines.UseSpaces, source.Lines.GetTabStop(0), textUndoList))
							{
								this.UndoOperations(textUndoList, true);
								source.Position = position;
								this.Clear();
							}
							else
							{
								SelectionType selType = SelectionType.None;
								if (!isEmpty)
								{
									this.StoreSelection(source, out selType, out num, out index, out index2);
								}
								else
								{
									num = source.StorePosition(source.Position, true);
								}
								try
								{
									if (needFormat)
									{
										source.FormatText();
									}
									TextStrings lines = this.owner.Lines;
									bool flag = (syntaxParser.Options & SyntaxOptions.SmartIndent) != SyntaxOptions.None;
									for (int i = this.selectionRect.Top; i <= this.selectionRect.Bottom; i++)
									{
										StringItem item = lines.GetItem(i);
										if (item != null)
										{
											string @string = item.String;
											if (@string.TrimStart(new char[0]) != string.Empty || needIndent)
											{
												textUndoList.Clear();
												bool flag2;
												int num2 = syntaxParser.SmartFormatLine(i, @string, item.TextData, textUndoList, out flag2);
												if (!flag)
												{
													num2 = -1;
												}
												if (num2 >= 0 || textUndoList.Count > 0)
												{
													this.UndoOperations(i, textUndoList, false);
													if (num2 >= 0)
													{
														@string = item.String;
														int num3 = @string.Length - @string.TrimStart(new char[0]).Length;
														string text;
														if (flag2)
														{
															text = ((num2 >= 0) ? lines.GetIndentString(num2, 0, true) : string.Empty);
														}
														else
														{
															text = ((num2 >= 0) ? lines.GetIndentString(this.GetTabIndent(num2), 0) : string.Empty);
														}
														if (text != @string.Substring(0, num3))
														{
															if (num3 >= 0)
															{
																source.MoveTo(0, i);
																source.DeleteRight(num3);
															}
															source.Insert(text);
														}
													}
												}
											}
										}
									}
								}
								finally
								{
									if (!isEmpty)
									{
										this.RestoreSelection(source, selType, num, index, index2);
									}
									else
									{
										this.Clear();
										source.Position = source.RestorePosition(num);
									}
								}
							}
							source.SetLastParsed(Math.Min(source.FirstChanged, this.selectionRect.Top));
						}
						finally
						{
							source.EndUpdate();
						}
					}
				}
				finally
				{
					this.EndUpdate();
				}
			}
		}

	    protected bool GetSelectionForLine(int index, out int left, out int right, bool checkBounds)
		{
			return this.GetSelectionForLine(index, out left, out right, checkBounds, this.selectionType, this.selectionRect);
		}
		protected bool GetSelectionForLine(int index, out int left, out int right, bool checkBounds, SelectionType selType, Rectangle selRect)
		{
			bool flag = false;
			left = 0;
			right = 0;
			Point point = Point.Empty;
			Point point2 = Point.Empty;
			if (selType != SelectionType.None)
			{
				DisplayStrings displayLines = this.owner.DisplayLines;
				point = displayLines.PointToDisplayPoint(selRect.Left, selRect.Top, this.atTopLeftEnd);
				point2 = displayLines.PointToDisplayPoint(selRect.Right, selRect.Bottom, this.atBottomRightEnd);
				flag = (index >= point.Y && index <= point2.Y);
				if (flag)
				{
					if (this.selectionType == SelectionType.Block || point.Y == point2.Y)
					{
						left = point.X;
						right = point2.X;
						if ((this.options & SelectionOptions.ExtendedBlockMode) != SelectionOptions.None && this.selectionType == SelectionType.Block && left == right && point.Y != point2.Y)
						{
							if (left != 0 || index != point2.Y)
							{
								right = int.MaxValue;
							}
							left = 0;
						}
					}
					else
					{
						if (index == point.Y)
						{
							left = point.X;
							right = int.MaxValue;
						}
						else
						{
							if (index == point2.Y)
							{
								left = 0;
								right = point2.X;
							}
							else
							{
								left = 0;
								right = int.MaxValue;
							}
						}
					}
					this.SwapMaxInt(ref left, ref right);
				}
			}
			return flag && (!checkBounds || right > left || (this.selectionType == SelectionType.Block && point.Y != point2.Y));
		}
		protected bool IsSelectionRectEmpty(Rectangle rect)
		{
			return this.IsSelectionRectEmpty(this.selectionType, rect);
		}
		protected bool IsSelectionRectEmpty(SelectionType selectionType, Rectangle rect)
		{
			bool result;
			switch (selectionType)
			{
			case SelectionType.Stream:
				result = (rect.Height < 0 || (rect.Height == 0 && rect.Width <= 0));
				break;
			case SelectionType.Block:
			{
				DisplayStrings displayLines = this.owner.DisplayLines;
				result = (rect.Height < 0 || displayLines.PointToDisplayPoint(rect.Left, rect.Top, this.atTopLeftEnd).X > displayLines.PointToDisplayPoint(rect.Right, rect.Bottom, this.atBottomRightEnd).X);
				break;
			}
			default:
				result = true;
				break;
			}
			return result;
		}
		protected bool IsSelectionRectEmpty()
		{
			return this.IsSelectionRectEmpty(this.selectionRect);
		}
		protected void UpdateSelStart(Point position, bool checkIfEmpty)
		{
			if (!checkIfEmpty || this.selectionType == SelectionType.None || !this.IsValidSelectionPoint(position))
			{
				this.selStart = position;
			}
		}
		protected void DeleteRight(bool deleteWord)
		{
			if (this.ShouldDeleteBlock())
			{
				this.Delete();
			}
			else
			{
				if (this.owner.Position.X >= this.owner.Lines.GetLength(this.owner.Position.Y))
				{
					this.owner.Source.UnBreakLine();
				}
				else
				{
					if (deleteWord)
					{
						bool flag = true;
						this.owner.Source.BeginUpdate(UpdateReason.Delete);
						this.BeginUpdate();
						try
						{
							this.SelectWordRight();
							flag = this.Delete();
						}
						finally
						{
							this.EndUpdate();
							this.owner.Source.EndUpdate();
						}
						if (!flag && !this.IsEmpty)
						{
							this.Clear();
						}
					}
					else
					{
						this.owner.Source.DeleteRight(1);
					}
				}
			}
		}
		protected void DeleteLeft(bool deleteWord)
		{
			if (this.ShouldDeleteBlock())
			{
				this.Delete();
			}
			else
			{
				if (this.owner.Position.X == 0)
				{
					if (this.owner.Position.Y > 0)
					{
						this.owner.Source.BeginUpdate(UpdateReason.UnBreak);
						try
						{
							this.owner.MoveTo(this.owner.Lines.GetLength(this.owner.Position.Y - 1), this.owner.Position.Y - 1);
							this.owner.Source.UnBreakLine();
						}
						finally
						{
							this.owner.Source.EndUpdate();
						}
					}
				}
				else
				{
					if (deleteWord)
					{
						bool flag = true;
						this.BeginUpdate();
						this.owner.Source.BeginUpdate(UpdateReason.Delete);
						try
						{
							this.SelectWordLeft();
							flag = this.Delete();
						}
						finally
						{
							this.owner.Source.EndUpdate();
							this.EndUpdate();
						}
						if (!flag && !this.IsEmpty)
						{
							this.Clear();
						}
					}
					else
					{
						this.owner.Source.DeleteLeft(1);
					}
				}
			}
		}
        protected void StoreSelection(Circus.CodeEditor.TextSource.TextSource source, out SelectionType selType, out int index1, out int index2, out int index3)
		{
			selType = this.SelectionType;
			if (!this.IsEmpty)
			{
				index1 = source.StorePosition(this.selectionRect.Location);
				index2 = source.StorePosition(this.selectionRect.Location + this.selectionRect.Size);
			}
			else
			{
				index1 = -1;
				index2 = -1;
			}
			index3 = source.StorePosition(source.Position);
		}
        protected void RestoreSelection(Circus.CodeEditor.TextSource.TextSource source, SelectionType selType, int index1, int index2, int index3)
		{
			source.Position = source.RestorePosition(index3);
			if (index1 >= 0 && index2 >= 0)
			{
				Point selectionEnd = source.RestorePosition(index2);
				Point selectionStart = source.RestorePosition(index1);
				this.SetSelection(selType, selectionStart, selectionEnd);
			}
			else
			{
				this.Clear();
			}
		}
		protected bool ShouldDelete()
		{
			return (this.options & SelectionOptions.OverwriteBlocks) != SelectionOptions.None && (this.options & SelectionOptions.PersistentBlocks) == SelectionOptions.None && !this.IsEmpty;
		}
		protected bool ShouldDeleteBlock()
		{
			return (this.options & SelectionOptions.PersistentBlocks) == SelectionOptions.None && !this.IsEmpty;
		}
		protected virtual bool DragScroll(Point pt)
		{
			Rectangle clientRect = this.owner.ClientRect;
			int windowOriginX = this.owner.Scrolling.WindowOriginX;
			int windowOriginY = this.owner.Scrolling.WindowOriginY;
			bool scrollByPixels = this.owner.Scrolling.ScrollByPixels;
			int lineHeight = this.owner.Painter.lineHeight;
			int fontWidth = this.owner.Painter.FontWidth;
			if (pt.Y - lineHeight < clientRect.Top)
			{
				this.owner.Scrolling.WindowOriginY -= (scrollByPixels ? lineHeight : 1);
			}
			else
			{
				if (pt.Y + lineHeight > clientRect.Bottom)
				{
					this.owner.Scrolling.WindowOriginY += (scrollByPixels ? lineHeight : 1);
				}
				else
				{
					if (pt.X - fontWidth < clientRect.Left)
					{
						this.owner.Scrolling.WindowOriginX -= (scrollByPixels ? fontWidth : 1);
					}
					else
					{
						if (pt.X + fontWidth > clientRect.Right)
						{
							this.owner.Scrolling.WindowOriginX += (scrollByPixels ? fontWidth : 1);
						}
					}
				}
			}
			return windowOriginX != this.owner.Scrolling.WindowOriginX || windowOriginY != this.owner.Scrolling.WindowOriginY;
		}
		protected virtual bool NeedDragScroll(Point pt)
		{
			Rectangle clientRect = this.owner.ClientRect;
			Rectangle rectangle = clientRect;
			rectangle.Inflate(-this.owner.Painter.FontWidth, -this.owner.Painter.lineHeight);
			bool result;
			if (this.owner.WordWrap)
			{
				if (!this.owner.WrapAtMargin)
				{
					result = (pt.Y >= clientRect.Top && pt.Y <= clientRect.Bottom && (pt.Y < rectangle.Top || pt.Y > rectangle.Bottom));
					return result;
				}
				if (pt.X >= this.owner.DisplayToScreen(this.owner.EditMargin.Position, 0).X)
				{
					result = (pt.Y >= clientRect.Top && pt.Y <= clientRect.Bottom && (pt.Y < rectangle.Top || pt.Y > rectangle.Bottom));
					return result;
				}
			}
			result = (clientRect.Contains(pt) && !rectangle.Contains(pt));
			return result;
		}
		protected bool IsPosInSelection(int x, int y, bool checkEnd)
		{
			bool result;
			if (!this.IsEmpty)
			{
				Point point = this.owner.DisplayLines.PointToDisplayPoint(x, y);
				int num;
				int num2;
				if (this.GetSelectionForLine(point.Y, out num, out num2))
				{
					result = (point.X >= num && (point.X < num2 || (checkEnd && point.X == num2)));
					return result;
				}
			}
			result = false;
			return result;
		}
		protected virtual void OnSelectionStateChanged()
		{
		}
		protected virtual void OnForeColorChanged()
		{
			this.Invalidate();
		}
		protected virtual void OnBackColorChanged()
		{
			this.Invalidate();
		}
		protected virtual void OnInActiveForeColorChanged()
		{
			this.Invalidate();
		}
		protected virtual void OnBorderColorChanged()
		{
			this.Invalidate();
		}
		protected virtual void OnInActiveBackColorChanged()
		{
			this.Invalidate();
		}
		protected virtual void OnAllowedSelectionModeChanged()
		{
			this.SetSelection(this.selectionType, this.selectionRect);
		}
		protected IDataObject GetDataObject()
		{
			IDataObject result;
			try
			{
				result = Clipboard.GetDataObject();
			}
			catch
			{
				result = null;
			}
			return result;
		}
		public Selection2()
		{
			this.moveSelection = new KeyEvent(this.MoveSelection);
			this.tabifyLineEvent = new TextUndoEvent(this.TabifyLine);
			this.unTabifyLineEvent = new TextUndoEvent(this.UnTabifyLine);
			this.indentLineEvent = new TextUndoEvent(this.IndentLine);
			this.unIndentLineEvent = new TextUndoEvent(this.UnIndentLine);
			this.lowerCaseLineEvent = new TextUndoEvent(this.LowerCaseLine);
			this.upperCaseLineEvent = new TextUndoEvent(this.UpperCaseLine);
			this.capitalizeLineEvent = new TextUndoEvent(this.CapitalizeLine);
			this.deleteWhiteSpaceEvent = new TextUndoEvent(this.DeleteWhiteSpace);
			this.commentLineEvent = new TextUndoEvent(this.CommentLine);
			this.uncommentLineEvent = new TextUndoEvent(this.UncommentLine);
			this.commentMultiLineEvent = new TextUndoEventEx(this.CommentMultiLine);
			this.uncommentMultiLineEvent = new TextUndoEventEx(this.UncommentMultiLine);
			this.selTimer = new Timer();
			this.selTimer.Enabled = false;
			this.selTimer.Interval = EditConsts.DefaultSelDelay;
			this.selTimer.Tick += new EventHandler(this.OnSelect);
			this.undoComparer = new Selection2.UndoComparer();
		}
		public Selection2(CodeEditor owner) : this()
		{
			this.owner = owner;
		}
		~Selection2()
		{
			this.Dispose(false);
		}
	
		protected virtual void OnOptionsChanged()
		{
			if ((SelectionOptions.DisableSelection & this.options) != SelectionOptions.None)
			{
				this.Clear();
			}
			if (this.owner != null)
			{
				this.owner.OnStateChanged(this, NotifyState.SelectionOptionsChanged);
			}
			this.Invalidate();
		}
		protected bool CanCommentSelection(string start, string end)
		{
			string text = this.owner.Lines[this.selectionRect.Top].TrimStart(new char[0]);
			bool result;
			if (text.StartsWith(start))
			{
				result = false;
			}
			else
			{
				text = this.owner.Lines[(this.selectionRect.Right == 0) ? (this.selectionRect.Bottom - 1) : this.selectionRect.Bottom].TrimEnd(new char[0]);
				result = !text.EndsWith(end);
			}
			return result;
		}
		protected bool CanUncommentSelection(string start, string end)
		{
			string text = this.owner.Lines[this.selectionRect.Top].TrimStart(new char[0]);
			bool result;
			if (!text.StartsWith(start))
			{
				result = false;
			}
			else
			{
				text = this.owner.Lines[(this.selectionRect.Right == 0) ? (this.selectionRect.Bottom - 1) : this.selectionRect.Bottom].TrimEnd(new char[0]);
				result = text.EndsWith(end);
			}
			return result;
		}
		protected virtual void ChangeBlock(TextUndoEvent action, TextUndoEventEx actionEx, bool changeIfEmpty, bool extendFirstLine)
		{
			if (changeIfEmpty || !this.IsEmpty)
			{
                Circus.CodeEditor.TextSource.TextSource source = this.owner.Source;
				TextUndoList textUndoList = new TextUndoList();
				int num = 0;
				int num2 = 0;
				if (this.IsEmpty)
				{
					string text = source.Lines[source.Position.Y];
					if (extendFirstLine || source.Position.X < text.Length)
					{
						source.BeginUpdate(UpdateReason.Other);
						try
						{
							Point position = source.Position;
							if (extendFirstLine)
							{
								num = position.X;
								if (actionEx != null)
								{
									actionEx(new Range(position, position), position.Y, text, textUndoList);
								}
								else
								{
									action(text, textUndoList);
								}
								source.MoveToChar(this.UndoOperations(position.Y, textUndoList, false) + num);
							}
							else
							{
								char c = text[position.X];
								if (actionEx != null)
								{
									actionEx(new Range(position, position), position.Y, c.ToString(), textUndoList);
								}
								else
								{
									action(c.ToString(), textUndoList);
								}
								foreach (TextUndo current in textUndoList)
								{
									current.Start += position.X;
								}
								this.UndoOperations(position.Y, textUndoList, false);
							}
						}
						finally
						{
							source.EndUpdate();
						}
					}
				}
				else
				{
					this.BeginUpdate();
					source.BeginUpdate(UpdateReason.Other);
					try
					{
						num = 0;
						num2 = 0;
						if (extendFirstLine)
						{
							Rectangle rectangle = this.SelectionRect;
							num = rectangle.Left;
							this.SelectionRect = new Rectangle(0, rectangle.Top, rectangle.Right, rectangle.Height);
						}
						IList<Range> list = new List<Range>();
						Range range = new Range(this.selectionRect.Left, this.selectionRect.Top, this.selectionRect.Right, this.selectionRect.Bottom);
						if (this.selectionType == SelectionType.Stream && this.selectionRect.Right == 0)
						{
							range.EndPoint = new Point(int.MaxValue, range.EndPoint.Y - 1);
						}
						for (int i = range.StartPoint.Y; i <= range.EndPoint.Y; i++)
						{
							list.Clear();
							this.GetSelectedBounds(i, list);
							textUndoList.Clear();
							foreach (Range current2 in list)
							{
								int count = textUndoList.Count;
								string text;
								if (extendFirstLine && i == this.selectionRect.Bottom && i != this.selectionRect.Top)
								{
									text = this.SafeSubString(this.owner.Lines[current2.StartPoint.Y], 0, int.MaxValue);
								}
								else
								{
									text = this.SafeSubString(this.owner.Lines[current2.StartPoint.Y], current2.StartPoint.X, current2.EndPoint.X);
								}
								if (actionEx != null)
								{
									actionEx(range, i, text, textUndoList);
								}
								else
								{
									action(text, textUndoList);
								}
								for (int j = count; j < textUndoList.Count; j++)
								{
									textUndoList[j].Start += current2.StartPoint.X;
								}
							}
							int num3 = this.UndoOperations(i, textUndoList, true);
							if (extendFirstLine)
							{
								if (i == this.selectionRect.Top)
								{
									num += num3;
								}
								if (i == this.selectionRect.Bottom)
								{
									num2 += num3;
								}
							}
						}
						if (extendFirstLine)
						{
							Rectangle rectangle = this.SelectionRect;
							if (actionEx != null)
							{
								if (range.EndPoint.Y == int.MaxValue)
								{
									range.EndPoint = new Point(0, range.EndPoint.Y + 1);
								}
								this.SetSelection(this.SelectionType, range.StartPoint, range.EndPoint);
							}
							else
							{
								this.SetSelection(this.SelectionType, new Point(Math.Max(rectangle.Left + num, 0), rectangle.Top), new Point(rectangle.Right + num2, rectangle.Bottom));
							}
						}
					}
					finally
					{
						source.EndUpdate();
						this.EndUpdate();
					}
				}
			}
		}
	
		public virtual void SetSelection(SelectionType selectionType, Rectangle selectionRect)
		{
			this.CheckSelectionMode(ref this.selectionType);
			bool flag = false;
			this.UpdateSelRect(ref this.selectionType, selectionType, ref this.selectionRect, selectionRect, ref flag);
			if (flag)
			{
				this.OnSelectionChanged();
			}
			if (this.IsEmpty)
			{
				this.selectionType = SelectionType.None;
			}
		}
		public virtual void OnSelectionChanged()
		{
			if (this.updateCount == 0)
			{
				this.owner.OnStateChanged(this, NotifyState.SelectionChanged);
				if (this.SelectionChanged != null)
				{
					this.SelectionChanged(this, EventArgs.Empty);
				}
			}
		}
		public virtual void OnSelect(object source, EventArgs e)
		{
			if (this.selectionState != SelectionState.None && this.owner.Source.UpdateCount <= 0)
			{
				Point pt = this.owner.PointToClient(Cursor.Position);
				bool lineEnd = false;
				Point point = Point.Empty;
                Circus.CodeEditor.TextSource.TextSource source2 = this.owner.Source;
				NavigateOptions navigateOptions = source2.NavigateOptions;
				try
				{
					source2.SetNavigateOptions(navigateOptions & ~NavigateOptions.BeyondEof);
					point = this.owner.ScreenToText(pt.X, pt.Y, ref lineEnd);
				}
				finally
				{
					source2.SetNavigateOptions(navigateOptions);
				}
				if (!point.Equals(this.selEnd) || this.selectionState == SelectionState.SelectLine)
				{
					DisplayStrings displayLines = this.owner.DisplayLines;
					switch (this.selectionState)
					{
					case SelectionState.Drag:
						if (this.owner.ClientRect.Contains(pt) && !this.NeedDragScroll(pt))
						{
							this.BeginUpdate();
							displayLines.DisableUpdate();
							try
							{
								displayLines.LineEnd = lineEnd;
								this.owner.Position = point;
							}
							finally
							{
								displayLines.EnableUpdate();
								this.EndUpdate();
							}
						}
						break;
					case SelectionState.Select:
						this.BeginUpdate();
						displayLines.DisableUpdate();
						try
						{
							this.selEnd = point;
							displayLines.LineEnd = lineEnd;
							this.SelectBlock((e != null) ? SelectionType.None : this.selectionType, this.CanSelectBlock() ? SelectionType.Block : SelectionType.Stream, this.selStart, this.moveSelection);
						}
						finally
						{
							displayLines.EnableUpdate();
							this.EndUpdate();
						}
						break;
					case SelectionState.SelectWord:
						this.BeginUpdate();
						displayLines.DisableUpdate();
						try
						{
							displayLines.LineEnd = lineEnd;
							this.selForward = (this.selEnd.Y > this.selStart.Y || (this.selEnd.Y == this.selStart.Y && this.selEnd.X > this.selStart.X));
							Point point2 = this.selStart;
							this.UpdateWordSelection(ref point2, !this.selForward);
							this.selEnd = point;
							this.SelectBlock((e != null) ? SelectionType.None : this.selectionType, this.CanSelectBlock() ? SelectionType.Block : SelectionType.Stream, point2, this.moveSelection);
						}
						finally
						{
							displayLines.EnableUpdate();
							this.EndUpdate();
						}
						break;
					case SelectionState.SelectLine:
						this.BeginUpdate();
						displayLines.DisableUpdate();
						try
						{
							displayLines.LineEnd = lineEnd;
							Point point2 = this.selStart;
							if (point.Y < this.selStart.Y)
							{
								point2 = new Point(0, this.selStart.Y + 1);
							}
							else
							{
								if (point.Y >= this.selStart.Y)
								{
									point2.X = 0;
								}
							}
							if (point.X != 0)
							{
								point2.X = 0;
								this.selectionState = SelectionState.Select;
							}
							else
							{
								if (point.Y >= this.selStart.Y)
								{
									point.Y++;
								}
							}
							if (!this.selEnd.Equals(point) || !this.selStart.Equals(point2))
							{
								this.selEnd = point;
								this.SelectBlock((e != null) ? SelectionType.None : this.selectionType, this.CanSelectBlock() ? SelectionType.Block : SelectionType.Stream, point2, this.moveSelection);
							}
						}
						finally
						{
							displayLines.EnableUpdate();
							this.EndUpdate();
						}
						break;
					}
				}
			}
		}
		public virtual void UpdateSelStart(Point position)
		{
			this.UpdateSelStart(position, false);
		}
		public virtual void UpdateSelRange(Point start, Point end)
		{
			this.selStart = start;
			this.selEnd = end;
		}
		public virtual void UpdateSelStart(bool checkIfEmpty)
		{
			this.UpdateSelStart(this.owner.Position, checkIfEmpty);
		}
		public virtual void StartSelection()
		{
			this.selTimer.Start();
		}
		public void EndSelection()
		{
			if (this.selectionState != SelectionState.None)
			{
				this.selTimer.Stop();
				this.selectionState = SelectionState.None;
				this.selForward = false;
			}
		}
		public virtual bool ScrollIfNeeded(Point pt)
		{
			return this.NeedDragScroll(pt) && this.DragScroll(pt);
		}
		public virtual bool IsValidSelectionPoint(Point position)
		{
			bool result;
			switch (this.selectionType)
			{
			case SelectionType.Stream:
				result = ((this.selectionRect.Top == position.Y && this.selectionRect.Left == position.X) || (this.selectionRect.Bottom == position.Y && this.selectionRect.Right == position.X));
				break;
			case SelectionType.Block:
			{
				DisplayStrings displayLines = this.owner.DisplayLines;
				Point point = displayLines.PointToDisplayPoint(this.selectionRect.Left, this.selectionRect.Top, this.atTopLeftEnd);
				Point point2 = displayLines.PointToDisplayPoint(this.selectionRect.Right, this.selectionRect.Bottom, this.atBottomRightEnd);
				Point point3 = displayLines.PointToDisplayPoint(position);
				result = ((point.Y == point3.Y || point2.Y == point3.Y) && (point.X == point3.X || point2.X == point3.X));
				break;
			}
			default:
				result = true;
				break;
			}
			return result;
		}
		public virtual void UpdateSelection()
		{
			if (!this.IsEmpty && ((this.options & SelectionOptions.HideSelection) != SelectionOptions.None || this.ForeColor != this.InActiveForeColor || this.owner.selectionBackColor != this.owner.inactivedSelectionBackColor))
			{
				this.Invalidate();
			}
		}
		public virtual void PositionChanged(int x, int y, int deltaX, int deltaY)
		{
			if (this.updateCount == 0 && !this.IsEmpty)
			{
				Point location = this.selectionRect.Location;
				Point point = new Point(this.selectionRect.Right, this.selectionRect.Bottom);
				bool flag = Range.UpdatePos(x, y, deltaX, deltaY, ref location, false);
				bool flag2 = Range.UpdatePos(x, y, deltaX, deltaY, ref point, true);
				if (flag || flag2)
				{
					this.SetSelection(this.selectionType, new Rectangle(location.X, location.Y, point.X - location.X, point.Y - location.Y));
				}
			}
		}
		public virtual Rectangle SelectionToScreen()
		{
			Rectangle result;
			if (!this.IsEmpty)
			{
				Point point = this.owner.TextToScreen(this.selectionRect.Location, this.atTopLeftEnd);
				Point point2 = this.owner.TextToScreen(this.selectionRect.Location + this.selectionRect.Size, this.atBottomRightEnd);
				result = new Rectangle(point.X, point.Y, point2.X - point.X, point2.Y - point.Y + this.owner.Painter.lineHeight);
			}
			else
			{
				result = new Rectangle(0, 0, 0, 0);
			}
			return result;
		}
		public virtual void Invalidate()
		{
			if (this.owner.Source.UpdateCount == 0)
			{
				Region selectionRegion = this.GetSelectionRegion(this.selectionType, this.selectionRect);
				if (selectionRegion != null)
				{
					this.owner.Invalidate(selectionRegion, false);
					selectionRegion.Dispose();
				}
			}
		}
		public virtual void SetSelection(SelectionType selectionType, Point selectionStart, Point selectionEnd)
		{
			this.SetSelection(selectionType, new Rectangle(selectionStart.X, selectionStart.Y, selectionEnd.X - selectionStart.X, selectionEnd.Y - selectionStart.Y));
		}
		public virtual void SelectCharLeft()
		{
			this.SelectCharLeft(SelectionType.Stream);
		}
		public virtual void SelectCharLeft(SelectionType selectionType)
		{
			this.SelectBlock(selectionType, this.KeyHandlers.moveCharLeftEvent);
		}
		public virtual void SelectCharRight()
		{
			this.SelectCharRight(SelectionType.Stream);
		}
		public virtual void SelectCharRight(SelectionType selectionType)
		{
			this.SelectBlock(selectionType, this.KeyHandlers.moveCharRightEvent);
		}
		public virtual void SelectWordLeft()
		{
			this.SelectWordLeft(SelectionType.Stream);
		}
		public virtual void SelectWordLeft(SelectionType selectionType)
		{
			this.SelectBlock(selectionType, this.KeyHandlers.moveWordLeftEvent);
		}
		public virtual void SelectWordRight()
		{
			this.SelectWordRight(SelectionType.Stream);
		}
		public virtual void SelectWordRight(SelectionType selectionType)
		{
			this.SelectBlock(selectionType, this.KeyHandlers.moveWordRightEvent);
		}
		public virtual void SelectLineUp()
		{
			this.SelectLineUp(SelectionType.Stream);
		}
		public virtual void SelectLineUp(SelectionType selectionType)
		{
			this.SelectBlock(selectionType, this.KeyHandlers.moveLineUpEvent);
		}
		public virtual void SelectLineDown()
		{
			this.SelectLineDown(SelectionType.Stream);
		}
		public virtual void SelectLineDown(SelectionType selectionType)
		{
			this.SelectBlock(selectionType, this.KeyHandlers.moveLineDownEvent);
		}
		public virtual void SelectPageUp()
		{
			this.SelectPageUp(SelectionType.Stream);
		}
		public virtual void SelectPageUp(SelectionType selectionType)
		{
			this.SelectBlock(selectionType, this.KeyHandlers.movePageUpEvent);
		}
		public virtual void SelectPageDown()
		{
			this.SelectPageDown(SelectionType.Stream);
		}
		public virtual void SelectPageDown(SelectionType selectionType)
		{
			this.SelectBlock(selectionType, this.KeyHandlers.movePageDownEvent);
		}
		public virtual void SelectScreenTop()
		{
			this.SelectScreenTop(SelectionType.Stream);
		}
		public virtual void SelectScreenTop(SelectionType selectionType)
		{
			this.SelectBlock(selectionType, this.KeyHandlers.moveScreenTopEvent);
		}
		public virtual void SelectScreenBottom()
		{
			this.SelectScreenBottom(SelectionType.Stream);
		}
		public virtual void SelectScreenBottom(SelectionType selectionType)
		{
			this.SelectBlock(selectionType, this.KeyHandlers.moveScreenBottomEvent);
		}
		public virtual void SelectLineBegin()
		{
			this.SelectLineBegin(SelectionType.Stream);
		}
		public virtual void SelectLineBegin(SelectionType selectionType)
		{
			this.SelectBlock(selectionType, this.KeyHandlers.moveLineBeginEvent);
		}
		public virtual void SelectLineEnd()
		{
			this.SelectLineEnd(SelectionType.Stream);
		}
		public virtual void SelectLineEnd(SelectionType selectionType)
		{
			this.SelectBlock(selectionType, this.KeyHandlers.moveLineEndEvent);
		}
		public virtual void SelectFileBegin()
		{
			this.SelectFileBegin(SelectionType.Stream);
		}
		public virtual void SelectFileBegin(SelectionType selectionType)
		{
			this.SelectBlock(selectionType, this.KeyHandlers.moveFileBeginEvent);
		}
		public virtual void SelectFileEnd()
		{
			this.SelectFileEnd(SelectionType.Stream);
		}
		public virtual void SelectFileEnd(SelectionType selectionType)
		{
			this.SelectBlock(selectionType, this.KeyHandlers.moveFileEndEvent);
		}
		public virtual void SelectLine()
		{
            Circus.CodeEditor.TextSource.TextSource source = this.owner.Source;
			NavigateOptions navigateOptions = source.NavigateOptions;
			try
			{
				source.SetNavigateOptions(navigateOptions | NavigateOptions.BeyondEof);
				Point position = this.owner.DisplayLines.PointToDisplayPoint(this.owner.Position);
				position.X = 0;
				Point selectionStart = this.owner.DisplayLines.DisplayPointToPoint(position);
				position.Y++;
				Point selectionEnd = this.owner.DisplayLines.DisplayPointToPoint(position);
				this.SetSelection(SelectionType.Stream, selectionStart, selectionEnd);
			}
			finally
			{
				source.SetNavigateOptions(navigateOptions);
			}
		}
		public virtual void SelectWord()
		{
			TextStrings lines = this.owner.Lines;
			Point position = this.owner.Position;
			string text = this.owner.Lines[position.Y];
			if (position.X > 0 && position.X < text.Length && ((this.owner.Lines.IsDelimiter(text, position.X) && !this.owner.Lines.IsDelimiter(text, position.X - 1)) || (this.owner.Lines.IsWhitespace(text, position.X) && !this.owner.Lines.IsWhitespace(text, position.X - 1))))
			{
				position.X--;
			}
			int num;
			int num2;
			if (lines.GetWord(position.Y, position.X, out num, out num2))
			{
				this.owner.MoveTo(num2 + 1, position.Y);
				this.selStart = new Point(num, position.Y);
				this.SetSelection(SelectionType.Stream, new Rectangle(num, position.Y, num2 - num + 1, 0));
			}
		}
		public virtual void SelectAll()
		{
			if (this.owner.Lines.Count > 0)
			{
				this.selStart = this.owner.Position;
				this.SetSelection(SelectionType.Stream, new Rectangle(0, 0, this.owner.Lines.GetLength(this.owner.Lines.Count - 1), this.owner.Lines.Count - 1));
			}
		}
		public virtual void SelectToOpenBrace()
		{
			this.SelectBlock((this.SelectionType != SelectionType.None) ? this.SelectionType : SelectionType.Stream, this.KeyHandlers.moveToOpenBraceEvent);
		}
		public virtual void SelectToCloseBrace()
		{
			this.SelectBlock((this.SelectionType != SelectionType.None) ? this.SelectionType : SelectionType.Stream, this.KeyHandlers.moveToCloseBraceEvent);
		}
		public virtual void SelectToBrace()
		{
			Point position = this.owner.Position;
			bool flag = false;
			bool flag2 = false;
			if (Array.IndexOf<char>(this.owner.Braces.OpenBraces, this.owner.Lines.GetCharAt(position)) >= 0)
			{
				flag = false;
				flag2 = true;
			}
			else
			{
				if (Array.IndexOf<char>(this.owner.Braces.ClosingBraces, this.owner.Lines.GetCharAt(position)) >= 0)
				{
					flag = false;
					flag2 = true;
				}
				else
				{
					if (position.X > 0 && Array.IndexOf<char>(this.owner.Braces.OpenBraces, this.owner.Lines.GetCharAt(new Point(position.X - 1, position.Y))) >= 0)
					{
						flag = true;
						flag2 = true;
					}
					else
					{
						if (position.X > 0 && Array.IndexOf<char>(this.owner.Braces.ClosingBraces, this.owner.Lines.GetCharAt(new Point(position.X - 1, position.Y))) >= 0)
						{
							flag = false;
							flag2 = false;
						}
					}
				}
			}
			this.SelectBlock(this.selectionType, (this.SelectionType != SelectionType.None) ? this.SelectionType : SelectionType.Stream, position, this.KeyHandlers.moveToBraceEvent);
			if ((flag || flag2) && !this.owner.Position.Equals(position) && !this.IsEmpty)
			{
				Rectangle rectangle = this.SelectionRect;
				if (flag && rectangle.X > 0)
				{
					rectangle.X--;
					rectangle.Width++;
				}
				if (flag2)
				{
					rectangle.Width++;
				}
				this.SetSelection(this.selectionType, rectangle);
			}
		}
		public virtual void CommentSelection()
		{
			if (this.owner.Lexer is SyntaxParser)
			{
				if (this.IsEmpty)
				{
					this.SelectLine();
				}
				this.SelectionType = SelectionType.Stream;
				string start;
				string end;
				if (this.owner.Lexer is SyntaxParser && ((SyntaxParser)this.owner.Lexer).GetMultiLineComment(out start, out end))
				{
					if (this.CanCommentSelection(start, end))
					{
						this.ChangeBlock(null, this.commentMultiLineEvent, false, true);
					}
				}
				else
				{
					this.ChangeBlock(this.commentLineEvent, false, true);
				}
			}
		}
		public virtual void UncommentSelection()
		{
			if (this.owner.Lexer is SyntaxParser)
			{
				if (this.IsEmpty)
				{
					this.SelectLine();
				}
				this.SelectionType = SelectionType.Stream;
				string start;
				string end;
				if (this.owner.Lexer is SyntaxParser && ((SyntaxParser)this.owner.Lexer).GetMultiLineComment(out start, out end))
				{
					if (this.CanUncommentSelection(start, end))
					{
						this.ChangeBlock(null, this.uncommentMultiLineEvent, false, true);
					}
				}
				else
				{
					this.ChangeBlock(this.uncommentLineEvent, false, true);
				}
			}
		}
		public virtual void SmartFormat()
		{
			this.SmartFormat(true, true, false, this.owner.Position.Y);
		}
		public virtual void SmartFormat(int line)
		{
			this.SmartFormat(false, false, false, line);
		}
		public virtual bool SmartFormat(char ch)
		{
			bool result;
			if ((this.Options & SelectionOptions.SmartFormat) != SelectionOptions.None)
			{
                Circus.CodeEditor.TextSource.TextSource source = this.owner.Source;
				if (source.NeedFormatText())
				{
					SyntaxParser syntaxParser = source.Lexer as SyntaxParser;
					int num = Array.IndexOf<char>(syntaxParser.SmartFormatChars, ch);
					if (num >= 0)
					{
						this.SmartFormatBlock(num == 0);
						result = true;
						return result;
					}
				}
			}
			result = false;
			return result;
		}
		public virtual void SmartIndent()
		{
			if ((this.Options & SelectionOptions.SmartFormat) != SelectionOptions.None && this.owner.Source.NeedIndentText())
			{
                Circus.CodeEditor.TextSource.TextSource source = this.owner.Source;
				SyntaxParser syntaxParser = (SyntaxParser)source.Lexer;
				Point position;
				SyntaxNode autoFormatNode = syntaxParser.GetAutoFormatNode(source.Position, true, out position);
				if (autoFormatNode != null)
				{
					syntaxParser.ReparseBlock(position);
					this.BeginUpdate();
					source.BeginUpdate(UpdateReason.Insert);
					try
					{
						int index = source.StorePosition(source.Position);
						this.Clear();
						this.SmartFormat(false, false, true, this.owner.Position.Y);
						this.Clear();
						source.State |= NotifyState.Edit;
						source.Position = source.RestorePosition(index);
					}
					finally
					{
						source.EndUpdate();
						this.EndUpdate();
					}
				}
			}
		}
		public virtual bool SmartIndent(char ch)
		{
            Circus.CodeEditor.TextSource.TextSource source = this.owner.Source;
			bool result;
			if (source.NeedIndentText())
			{
				SyntaxParser syntaxParser = source.Lexer as SyntaxParser;
				if (Array.IndexOf<char>(syntaxParser.AutoIndentChars, ch) >= 0)
				{
					this.SmartIndent();
					result = true;
					return result;
				}
			}
			result = false;
			return result;
		}
		public virtual void SmartFormatBlock(bool extended)
		{
			if ((this.Options & SelectionOptions.SmartFormat) != SelectionOptions.None && this.owner.Source.NeedFormatText())
			{
                Circus.CodeEditor.TextSource.TextSource source = this.owner.Source;
				SyntaxParser syntaxParser = (SyntaxParser)source.Lexer;
				Point position = source.Position;
				TextUndoList operations = new TextUndoList();
				syntaxParser.Prepare(source.FileName, source.Lines, null, false);
				if (syntaxParser.SmartFormat(ref position, source.Lines.UseSpaces, source.Lines.GetTabStop(0), operations))
				{
					this.BeginUpdate();
					try
					{
						this.UndoOperations(operations, true);
						source.HighlightBraces();
						source.InvalidateSyntaxErrors();
						source.Position = position;
						this.Clear();
					}
					finally
					{
						this.EndUpdate();
					}
				}
				else
				{
					syntaxParser.SaveSyntaxTree();
					try
					{
						source.FormatText(true, false);
						Point point;
						SyntaxNode autoFormatNode = syntaxParser.GetAutoFormatNode(position, extended, out point);
						if (autoFormatNode != null && (extended || !autoFormatNode.ContainsErrors()))
						{
							Range range = autoFormatNode.Range;
							this.BeginUpdate();
							try
							{
								this.SetSelection(SelectionType.Stream, range.StartPoint, range.EndPoint);
								int index = source.StorePosition(source.Position);
								this.SmartFormat(false, false, false, this.owner.Position.Y);
								if (this.owner.Braces.BracesOptions != BracesOptions.None && !this.owner.Braces.UseRoundRect)
								{
									source.TempHighlightBraces(new Rectangle[]
									{
										new Rectangle(this.selectionRect.Left, this.selectionRect.Top, point.X - this.selectionRect.Left, point.Y - this.selectionRect.Top)
									});
								}
								source.Position = source.RestorePosition(index);
								source.HighlightBraces();
								source.InvalidateSyntaxErrors();
								this.Clear();
							}
							finally
							{
								this.EndUpdate();
							}
						}
					}
					finally
					{
						syntaxParser.RestoreSyntaxTree();
					}
				}
			}
		}
		public virtual void SmartFormatDocument()
		{
            Circus.CodeEditor.TextSource.TextSource source = this.owner.Source;
			if (source.NeedFormatText())
			{
				this.BeginUpdate();
				source.BeginUpdate(UpdateReason.Other);
				try
				{
					Point point = this.selStart;
					SelectionType selType;
					int index;
					int index2;
					int index3;
					this.StoreSelection(source, out selType, out index, out index2, out index3);
					try
					{
						this.SelectAll();
						this.SmartFormat();
					}
					finally
					{
						this.RestoreSelection(source, selType, index, index2, index3);
						this.selStart = point;
					}
				}
				finally
				{
					source.EndUpdate();
					this.EndUpdate();
				}
			}
		}
		public virtual void Tabify()
		{
			this.ChangeBlock(this.tabifyLineEvent);
		}
		public virtual void UnTabify()
		{
			this.ChangeBlock(this.unTabifyLineEvent);
		}
		public void Indent()
		{
			this.ChangeBlock(this.indentLineEvent, true, this.SelectionType != SelectionType.Block);
		}
		public virtual void UnIndent()
		{
			this.ChangeBlock(this.unIndentLineEvent, true, this.SelectionType != SelectionType.Block);
		}
		public virtual void LowerCase()
		{
			this.ChangeBlock(this.lowerCaseLineEvent, true, false);
		}
		public virtual void UpperCase()
		{
			this.ChangeBlock(this.upperCaseLineEvent, true, false);
		}
		public virtual void Capitalize()
		{
			this.ChangeBlock(this.capitalizeLineEvent, true, false);
		}
		public virtual void DeleteWhiteSpace()
		{
			if (this.IsEmpty)
			{
				string text = this.owner.Lines[this.owner.Position.Y];
				if (this.owner.Position.X < text.Length && this.owner.Position.X <= text.Length - text.TrimStart(new char[0]).Length)
				{
					this.SelectLineBegin();
					this.ChangeBlock(this.deleteWhiteSpaceEvent);
					this.Clear();
				}
			}
			else
			{
				this.ChangeBlock(this.deleteWhiteSpaceEvent);
			}
		}
		public virtual void ToggleOutlining()
		{
			DisplayStrings displayLines = this.owner.DisplayLines;
			List<Range> list = new List<Range>();
			if (!this.IsEmpty)
			{
				displayLines.GetOutlineRanges(list, this.selectionRect.Location, this.selectionRect.Location + this.selectionRect.Size);
			}
			if (list.Count == 0)
			{
				Point position = this.owner.Position;
				if (position.X > 0)
				{
					OutlineRange outlineRange = displayLines.GetOutlineRange(new Point(position.X - 1, position.Y));
					if (outlineRange != null && outlineRange.EndPoint.Equals(position))
					{
						list.Add(outlineRange);
					}
				}
				if (list.Count == 0)
				{
					OutlineRange outlineRange = displayLines.GetOutlineRange(this.owner.Position);
					if (outlineRange != null)
					{
						list.Add(outlineRange);
					}
				}
			}
			if (list.Count != 0)
			{
				displayLines.ToggleOutlining(list, null);
			}
		}
		public virtual void CollapseToDefinitions()
		{
			this.owner.DisplayLines.CollapseToDefinitions();
		}
		public virtual void SwapAnchor()
		{
			if (!this.IsEmpty)
			{
				this.BeginUpdate();
				try
				{
					if (this.owner.Position == this.selectionRect.Location + this.selectionRect.Size)
					{
						this.owner.Position = this.selectionRect.Location;
					}
					else
					{
						this.owner.Position = this.selectionRect.Location + this.selectionRect.Size;
					}
				}
				finally
				{
					this.EndUpdate();
				}
			}
		}
		public virtual bool CanCopy()
		{
			return !this.IsEmpty || (this.options & SelectionOptions.CopyLineWhenEmpty) != SelectionOptions.None;
		}
		public virtual bool CanCut()
		{
			return !this.owner.Source.ReadOnly && (!this.IsEmpty || (this.options & SelectionOptions.CopyLineWhenEmpty) != SelectionOptions.None) && !false;
		}
		public virtual bool CanPaste()
		{
			bool result;
		    int index = this.owner.Position.Y;
		    if (this.owner.ReadOnly || false)
			{
				result = false;
			}
			else
			{
				try
				{
					result = (Clipboard.ContainsText(TextDataFormat.UnicodeText) || (Clipboard.ContainsText(TextDataFormat.Text) && !false));
				}
				catch
				{
					result = false;
				}
			}
			return result;
		}
		public virtual void Copy()
		{
			if (this.CanCopy())
			{
				bool isEmpty = this.IsEmpty;
				if (isEmpty)
				{
					this.SelectLine();
				}
				this.WriteToClipboard(isEmpty);
				if ((this.options & SelectionOptions.DeselectOnCopy) != SelectionOptions.None || isEmpty)
				{
					this.Clear();
				}
			}
		}
		public virtual void Cut()
		{
			if (this.CanCut())
			{
				if (this.IsEmpty)
				{
					this.SelectLine();
				}
				this.WriteToClipboard(false);
				this.Delete();
			}
		}
		public virtual void Paste()
		{
			object obj = null;
			if (Clipboard.ContainsText(TextDataFormat.UnicodeText))
			{
				obj = Clipboard.GetData(DataFormats.UnicodeText);
			}
			else
			{
				if (Clipboard.ContainsText(TextDataFormat.Text))
				{
					obj = Clipboard.GetData(DataFormats.Text);
				}
			}
			if (obj != null)
			{
                Circus.CodeEditor.TextSource.TextSource source = this.owner.Source;
				this.BeginUpdate();
				try
				{
					object data = Clipboard.GetData(DataFormats.Serializable);
					source.BeginUpdate(UpdateReason.Delete);
					try
					{
						this.SetSelectedText((string)obj, (data is SelectionType && (SelectionType)data != SelectionType.None) ? ((SelectionType)data) : SelectionType.Stream, true);
						if ((this.options & SelectionOptions.ConvertToSpacesOnPaste) != SelectionOptions.None && this.owner.Lines.UseSpaces)
						{
							this.UnTabify();
						}
					}
					finally
					{
						source.EndUpdate();
					}
					if ((this.options & SelectionOptions.SmartFormat) != SelectionOptions.None && !this.IsEmpty && this.selectionRect.Height > 0)
					{
						SyntaxParser syntaxParser = this.owner.Source.NeedFormatText() ? ((SyntaxParser)this.owner.Lexer) : null;
						if (syntaxParser != null)
						{
							syntaxParser.SaveSyntaxTree();
							try
							{
								this.SmartFormat(true, false, false, this.owner.Position.Y);
							}
							finally
							{
								syntaxParser.RestoreSyntaxTree();
							}
						}
						else
						{
							this.SmartFormat();
						}
					}
					if ((this.options & SelectionOptions.PersistentBlocks) == SelectionOptions.None)
					{
						this.Clear();
					}
					this.UpdateSelStart(false);
				}
				finally
				{
					this.EndUpdate();
				}
			}
		}
		public virtual bool Delete()
		{
			bool result;
			if (this.owner.ReadOnly)
			{
				result = false;
			}
			else
			{
				bool flag = true;
				if (!this.IsEmpty)
				{
					this.BeginUpdate();
					try
					{
                        Circus.CodeEditor.TextSource.TextSource source = this.owner.Source;
						source.BeginUpdate(UpdateReason.Delete);
						try
						{
							if (this.selectionType == SelectionType.Stream)
							{
								flag = source.DeleteBlock(this.SelectionRect);
							}
							else
							{
								IList<Range> list = new List<Range>();
								for (int i = this.selectionRect.Top; i <= this.selectionRect.Bottom; i++)
								{
									this.GetSelectedBounds(i, list);
								}
								for (int i = list.Count - 1; i >= 0; i--)
								{
									Range range = list[i];
									source.MoveTo(range.StartPoint.X, range.StartPoint.Y);
									source.DeleteRight((range.EndPoint.X == int.MaxValue) ? range.EndPoint.X : (range.EndPoint.X - range.StartPoint.X));
									if (range.EndPoint.X == int.MaxValue)
									{
										source.UnBreakLine();
									}
								}
							}
						}
						finally
						{
							source.EndUpdate();
						}
						if (flag)
						{
							if (this.selectionType != SelectionType.Block)
							{
								this.Clear();
							}
						}
					}
					finally
					{
						this.EndUpdate();
					}
				}
				result = flag;
			}
			return result;
		}
		public virtual void Clear()
		{
			this.SelectionType = SelectionType.None;
		}
		public virtual bool Move(Point position, bool deleteOrigin)
		{
			bool flag = !this.IsPosInSelection(position) && !this.owner.Source.ReadOnly && !this.IsEmpty;
			if (flag)
			{
				bool flag2 = true;
				SelectionType selType = this.selectionType;
                Circus.CodeEditor.TextSource.TextSource source = this.owner.Source;
				this.BeginUpdate();
				source.BeginUpdate(UpdateReason.Other);
				try
				{
					int index = source.StorePosition(position);
					string selectedText = this.SelectedText;
					if (deleteOrigin)
					{
						flag2 = this.Delete();
					}
					source.Position = source.RestorePosition(index);
					if (flag2)
					{
						this.Clear();
						this.SetSelectedText(selectedText, selType);
					}
				}
				finally
				{
					source.EndUpdate();
					this.EndUpdate();
				}
				if (!flag2 && !this.IsEmpty)
				{
					this.Clear();
				}
			}
			return flag;
		}
		public virtual int BeginUpdate()
		{
			if (this.updateCount == 0)
			{
				this.oldSelectionRect = this.selectionRect;
				this.oldSelectionType = this.selectionType;
				this.oldPos = this.owner.Position;
			}
			this.updateCount++;
			return this.updateCount;
		}
		public virtual int EndUpdate()
		{
			this.updateCount--;
			if (this.updateCount == 0 && (!this.oldSelectionRect.Equals(this.selectionRect) || this.oldSelectionType != this.selectionType || !this.oldPos.Equals(this.owner.Position)))
			{
				this.OnSelectionChanged();
			}
			return this.updateCount;
		}
		public virtual void DeleteLeft()
		{
			this.DeleteLeft(false);
		}
		public virtual void DeleteRight()
		{
			this.DeleteRight(false);
		}
		public virtual void DeleteWordLeft()
		{
			this.DeleteLeft(true);
		}
		public virtual void DeleteWordRight()
		{
			this.DeleteRight(true);
		}
		public virtual void DeleteLine()
		{
			if (this.IsEmpty)
			{
				this.SelectLine();
			}
			this.Delete();
		}
		public virtual void CutLine()
		{
			if (this.IsEmpty)
			{
				this.SelectLine();
			}
			this.Cut();
		}
		public virtual void NewLine()
		{
			if (!this.owner.SingleLineMode)
			{
				bool flag = true;
                Circus.CodeEditor.TextSource.TextSource source = this.owner.Source;
				this.BeginUpdate();
				source.BeginUpdate(UpdateReason.Break);
				try
				{
					if (!this.owner.ProcessEnter())
					{
						if (this.ShouldDelete())
						{
							flag = this.Delete();
						}
						Point position = source.Position;
						if (source.NewLine())
						{
							if ((source.IndentOptions & IndentOptions.AutoIndent) != IndentOptions.None)
							{
								Point position2 = source.Position;
								string empty = string.Empty;
								bool flag2 = source.NeedAutoComplete() && source.Lines[position2.Y].Trim() == string.Empty && source.ProcessAutoComplete(out empty);
								if (flag2)
								{
									string[] array = StringItem.Split(empty);
									if (array.Length > 0)
									{
										string text = array[0];
										if (text != string.Empty)
										{
											source.MoveTo(source.Lines[position.Y].TrimEnd(new char[0]).Length, position.Y);
											source.Insert(text);
											source.MoveTo(position2);
										}
										string[] array2 = new string[array.Length - 1];
										Array.Copy(array, 1, array2, 0, array2.Length);
										source.InsertBlock(array2);
										if (array2.Length > 1)
										{
											this.SetSelection(SelectionType.Stream, position2, this.owner.Position);
											this.SmartFormat();
											source.Position = position2;
											this.Clear();
											if (source.Lines[source.Position.Y].Trim() == string.Empty)
											{
												source.DeleteLeft(source.Position.X);
												source.IndentLine();
											}
										}
									}
								}
								else
								{
									this.SmartIndent('\r');
								}
							}
						}
					}
				}
				finally
				{
					source.EndUpdate();
					if (!flag && !this.IsEmpty)
					{
						this.Clear();
					}
					this.EndUpdate();
				}
			}
		}
		public virtual void NewLineAbove()
		{
			if (!this.owner.ProcessEnter())
			{
				this.owner.Source.NewLineAbove();
			}
		}
		public virtual void NewLineBelow()
		{
			if (!this.owner.ProcessEnter())
			{
				this.owner.Source.NewLineBelow();
			}
		}
		public virtual void ProcessEscape()
		{
			this.SelectionType = SelectionType.None;
		}
		public virtual void ProcessTab()
		{
			if (!this.owner.ProcessTab(this.owner.Position))
			{
				if (this.IsEmpty || this.SelectedCount() == 1)
				{
					if (this.owner.Lines.UseSpaces)
					{
						TextStrings lines = this.owner.Lines;
						Point position = this.owner.Position;
						position.X = lines.TabPosToPos(lines[position.Y], position.X);
						int num = lines.GetTabStop(position.X) - position.X;
						if (num > 0)
						{
							this.InsertString(new string(' ', num));
						}
					}
					else
					{
						this.InsertString('\t'.ToString());
					}
				}
				else
				{
					if (!this.owner.Source.ReadOnly && !false)
					{
						this.Indent();
					}
				}
			}
		}
		public virtual void ProcessShiftTab()
		{
			if (!this.owner.ProcessShiftTab(this.owner.Position))
			{
				int num = this.IndexOfNonWhitespaceChar(this.owner.Lines[this.owner.Position.Y]);
				if (this.IsEmpty)
				{
					if (this.owner.Position.X <= num)
					{
						this.UnIndent();
					}
				}
				else
				{
					if (this.selectionRect.Height > 0 || this.selectionRect.Left <= num)
					{
						this.UnIndent();
					}
				}
			}
		}
		public virtual void ToggleOverWrite()
		{
			this.owner.Source.Overwrite = !this.owner.Source.Overwrite;
		}
		public virtual void InsertString(string s)
		{
			bool flag = true;
            Circus.CodeEditor.TextSource.TextSource source = this.owner.Source;
			bool flag2 = this.selectionType == SelectionType.Block && (this.options & SelectionOptions.ExtendedBlockMode) != SelectionOptions.None;
			if (this.selectionType == SelectionType.Block)
			{
				this.BeginUpdate();
			}
			source.BeginUpdate(UpdateReason.Insert);
			try
			{
				if (!flag2 && this.ShouldDelete())
				{
					flag = this.Delete();
				}
				bool flag3 = (this.owner.NavigateOptions & NavigateOptions.BeyondEol) == NavigateOptions.None;
				if (flag2)
				{
					IList<Range> list = new List<Range>();
					for (int i = this.selectionRect.Top; i <= this.selectionRect.Bottom; i++)
					{
						this.GetSelectedBounds(i, list);
					}
					int num = 0;
					int x = source.Position.X;
					bool flag4 = false;
					DisplayStrings displayLines = this.owner.DisplayLines;
					if (list.Count > 0)
					{
						Range range = list[0];
						Point point = (source.Position.Y == range.StartPoint.Y) ? source.Position : displayLines.DisplayPointToPoint(source.Position);
						num = ((this.selectionRect.Width > 0) ? (point.X - range.StartPoint.X) : 0);
						flag4 = (source.Position.X < range.EndPoint.X);
					}
					Point selectionEnd = Point.Empty;
					NavigateOptions navigateOptions = this.owner.NavigateOptions;
					if (flag3)
					{
						this.owner.SetNavigateOptions(this.owner.NavigateOptions | NavigateOptions.BeyondEol);
					}
					try
					{
						for (int i = list.Count - 1; i >= 0; i--)
						{
							Range range = list[i];
							if (flag4)
							{
								source.MoveTo(range.StartPoint.X + num, range.StartPoint.Y);
							}
							else
							{
								source.MoveTo(range.EndPoint.X, range.EndPoint.Y);
							}
							source.Insert(s);
							if (i == list.Count - 1)
							{
								selectionEnd = (flag4 ? new Point(source.Position.X - num + range.EndPoint.X - range.StartPoint.X, source.Position.Y) : source.Position);
							}
						}
					}
					finally
					{
						if (flag3)
						{
							this.owner.SetNavigateOptions(navigateOptions);
						}
					}
					if (!this.IsEmpty)
					{
						this.SetSelection(SelectionType.Block, this.SelectionRect.Location, selectionEnd);
					}
				}
				else
				{
					if (this.selectionType == SelectionType.Block)
					{
						IList<Range> list = new List<Range>();
						for (int i = this.selectionRect.Top; i <= this.selectionRect.Bottom; i++)
						{
							this.GetSelectedBounds(i, list);
						}
						int num = 0;
						if (list.Count > 0)
						{
							Range range = list[0];
							num = ((this.selectionRect.Width > 0) ? (source.Position.X - range.StartPoint.X) : 0);
						}
						NavigateOptions navigateOptions = this.owner.NavigateOptions;
						if (flag3)
						{
							this.owner.SetNavigateOptions(this.owner.NavigateOptions | NavigateOptions.BeyondEol);
						}
						try
						{
							for (int i = list.Count - 1; i >= 0; i--)
							{
								Range range = list[i];
								source.MoveTo(range.StartPoint.X + num, range.StartPoint.Y);
								source.Insert(s);
							}
						}
						finally
						{
							if (flag3)
							{
								this.owner.SetNavigateOptions(navigateOptions);
							}
						}
						this.SetSelection(SelectionType.Block, new Point(this.SelectionRect.Left + s.Length, this.SelectionRect.Top), new Point(this.SelectionRect.Left + s.Length, this.SelectionRect.Bottom));
					}
					else
					{
						source.Insert(s);
					}
				}
			}
			finally
			{
				source.EndUpdate();
				if (this.selectionType == SelectionType.Block)
				{
					this.EndUpdate();
				}
			}
			if (!flag && !this.IsEmpty)
			{
				this.Clear();
			}
		}
		public virtual void CharTransponse()
		{
			Point position = this.owner.Position;
			string text = this.owner.Lines[position.Y];
			if (text.Length >= 2)
			{
				position.X = Math.Max(Math.Min(position.X, text.Length - 1), 1);
                Circus.CodeEditor.TextSource.TextSource source = this.owner.Source;
				source.BeginUpdate(UpdateReason.Insert);
				try
				{
					char c = text[position.X];
					source.MoveToChar(position.X);
					source.DeleteRight(1);
					this.owner.MoveToChar(position.X - 1);
					source.Insert(c.ToString());
					source.MoveToChar(position.X + 1);
				}
				finally
				{
					source.EndUpdate();
				}
			}
		}
		public virtual void WordTransponse()
		{
			this.owner.Source.BeginUpdate(UpdateReason.Insert);
			try
			{
				Point position = this.owner.Position;
				if (this.SelectCurrentWord() && !this.IsEmpty)
				{
					Rectangle rectangle = this.SelectionRect;
					SelectionType selectionType = this.SelectionType;
					string selectedText = this.SelectedText;
					this.SelectNextWord();
					if (!this.IsEmpty)
					{
						string selectedText2 = this.SelectedText;
						this.Delete();
						this.InsertString(selectedText);
						this.owner.MoveTo(rectangle.Location);
						this.owner.Selection.SetSelection(selectionType, rectangle);
						this.Delete();
						this.InsertString(selectedText2);
						return;
					}
				}
				this.owner.Position = position;
			}
			finally
			{
				this.owner.Source.EndUpdate();
			}
		}
		public virtual void LineTransponse()
		{
			if (this.owner.Position.Y < this.owner.Lines.Count - 1)
			{
                Circus.CodeEditor.TextSource.TextSource source = this.owner.Source;
				source.BeginUpdate(UpdateReason.Insert);
				try
				{
					string text = this.owner.Lines[this.owner.Position.Y];
					this.owner.MoveLineBegin();
					source.DeleteRight(int.MaxValue);
					source.UnBreakLine();
					this.owner.MoveLineEnd();
					source.BreakLine();
					source.MoveTo(0, source.Position.Y + 1);
					source.Insert(text);
				}
				finally
				{
					source.EndUpdate();
				}
			}
		}
		public virtual bool CanDrag(Point position)
		{
			return !this.owner.Source.ReadOnly && (SelectionOptions.DisableDragging & this.options) == SelectionOptions.None && !this.IsPosInSelection(position);
		}
		public virtual void DragTo(Point position, bool deleteOrigin)
		{
			this.Move(position, deleteOrigin);
		}
		public virtual void ChangeBlock(StringEvent action)
		{
			this.ChangeBlock(action, false, false);
		}
		public virtual void ChangeBlock(TextUndoEvent action)
		{
			this.ChangeBlock(action, false, false);
		}
		public virtual void ChangeBlock(StringEvent action, bool changeIfEmpty, bool extendFirstLine)
		{
			if (changeIfEmpty || !this.IsEmpty)
			{
                Circus.CodeEditor.TextSource.TextSource source = this.owner.Source;
				if (this.IsEmpty)
				{
					string text = source.Lines[source.Position.Y];
					if (extendFirstLine || source.Position.X < text.Length)
					{
						source.BeginUpdate(UpdateReason.Other);
						try
						{
							if (extendFirstLine)
							{
								int num = source.Position.X - text.Length;
								source.MoveToChar(0);
								source.DeleteRight(int.MaxValue);
								text = action(text);
								num += text.Length;
								source.Insert(text);
								source.MoveToChar(num);
							}
							else
							{
								char c = text[source.Position.X];
								source.DeleteRight(1);
								source.Insert(action(c.ToString()));
							}
						}
						finally
						{
							source.EndUpdate();
						}
					}
				}
				else
				{
					int num = 0;
					if (extendFirstLine)
					{
						Rectangle rectangle = this.SelectionRect;
						num = rectangle.Left;
						this.SelectionRect = new Rectangle(0, rectangle.Top, rectangle.Right, rectangle.Height);
					}
					StringBuilder stringBuilder = new StringBuilder();
					int num2 = this.SelectedCount();
					for (int i = 0; i < num2; i++)
					{
						string text = this.SelectedString(i);
						string text2;
						if (i == num2 - 1 && this.selectionType == SelectionType.Stream && this.selectionRect.Right == 0)
						{
							text2 = text;
						}
						else
						{
							text2 = action(text);
						}
						if (extendFirstLine && i == 0)
						{
							num += text2.Length - text.Length;
						}
						stringBuilder.Append(text2);
						if (i < num2 - 1)
						{
							stringBuilder.Append(source.LineTerminator);
						}
					}
					this.SetSelectedText(stringBuilder.ToString(), (this.SelectionType != SelectionType.None) ? this.SelectionType : SelectionType.Stream);
					if (extendFirstLine)
					{
						Rectangle rectangle = this.SelectionRect;
						this.SetSelection(this.SelectionType, new Point(Math.Max(rectangle.Left + num, 0), rectangle.Top), new Point(rectangle.Right, rectangle.Bottom));
					}
				}
			}
		}
		public virtual void ChangeBlock(TextUndoEvent action, bool changeIfEmpty, bool extendFirstLine)
		{
			this.ChangeBlock(action, null, changeIfEmpty, extendFirstLine);
		}
		public virtual Point SelectionToTextPoint(Point position)
		{
			Point result;
			switch (this.selectionType)
			{
			case SelectionType.Stream:
				if (position.Y == 0)
				{
					result = new Point(position.X + this.selectionRect.Left, this.selectionRect.Top);
				}
				else
				{
					result = new Point(position.X, this.selectionRect.Top + position.Y);
				}
				break;
			case SelectionType.Block:
				result = new Point(position.X + this.selectionRect.Left, position.Y + this.selectionRect.Top);
				break;
			default:
				result = position;
				break;
			}
			return result;
		}
		public virtual Point TextToSelectionPoint(Point position)
		{
			Point result;
			switch (this.selectionType)
			{
			case SelectionType.Stream:
				if (position.Y == this.selectionRect.Top)
				{
					result = new Point(position.X - this.selectionRect.Left, 0);
				}
				else
				{
					result = new Point(position.X, position.Y - this.selectionRect.Top);
				}
				break;
			case SelectionType.Block:
				result = new Point(position.X - this.selectionRect.Left, position.Y - this.selectionRect.Top);
				break;
			default:
				result = position;
				break;
			}
			return result;
		}
		public virtual bool IsPosInSelection(Point position)
		{
			return this.IsPosInSelection(position.X, position.Y, false);
		}
		public virtual bool IsPosInSelection(int x, int y)
		{
			return this.IsPosInSelection(x, y, false);
		}
		public virtual bool GetSelectionForLine(int index, out int left, out int right)
		{
			return this.GetSelectionForLine(index, out left, out right, true);
		}
		public virtual int SelectedCount()
		{
			int result;
			if (this.selectionType == SelectionType.None)
			{
				result = 0;
			}
			else
			{
				result = this.SelectionRect.Bottom - this.SelectionRect.Top + 1;
			}
			return result;
		}
		public virtual string SelectedString(int index)
		{
			string result;
			if (this.IsEmpty)
			{
				result = null;
			}
			else
			{
				int top = this.selectionRect.Top;
				IList<Range> list = new List<Range>();
				this.GetSelectedBounds(index + top, list);
				if (list.Count == 0)
				{
					result = null;
				}
				else
				{
					switch (this.SelectionType)
					{
					case SelectionType.Stream:
					{
						Range range = list[0];
						result = this.SafeSubString(this.owner.Lines[range.StartPoint.Y], range.StartPoint.X, range.EndPoint.X);
						break;
					}
					case SelectionType.Block:
					{
						StringBuilder stringBuilder = new StringBuilder();
						for (int i = 0; i < list.Count; i++)
						{
							Range range = list[i];
							stringBuilder.Append(this.SafeSubString(this.owner.Lines[range.StartPoint.Y], range.StartPoint.X, range.EndPoint.X));
							if (i != list.Count - 1)
							{
								stringBuilder.Append(this.owner.LineTerminator);
							}
						}
						result = stringBuilder.ToString();
						break;
					}
					default:
						result = null;
						break;
					}
				}
			}
			return result;
		}
		public bool SelectCurrentWord()
		{
			TextStrings lines = this.owner.Lines;
			Point position = this.owner.Position;
			while (position.Y < lines.Count)
			{
				string text = lines[position.Y];
				int length = text.Length;
				while (position.X < length && lines.IsDelimiter(text, position.X))
				{
					position.X++;
				}
				if (position.X < length)
				{
					break;
				}
				position.Y++;
				position.X = 0;
			}
			if (position.Y < lines.Count)
			{
				this.owner.Position = position;
				this.SelectWord();
			}
			return position.Y < lines.Count;
		}
		public bool SelectNextWord()
		{
			TextStrings lines = this.owner.Lines;
			Point position = this.owner.Position;
			string text = lines[position.Y];
			while (position.X < text.Length && !lines.IsDelimiter(text, position.X))
			{
				position.X++;
			}
			this.owner.Position = position;
			return this.SelectCurrentWord();
		}
		public void SetSelectedText(string text, SelectionType selType)
		{
			this.SetSelectedText(text, selType, false);
		}
		public void SetSelectedText(string text, SelectionType selType, bool moveToEnd)
		{
			this.BeginUpdate();
            Circus.CodeEditor.TextSource.TextSource source = this.owner.Source;
			source.BeginUpdate(UpdateReason.Other);
			NavigateOptions navigateOptions = source.NavigateOptions;
			try
			{
				source.SetNavigateOptions(navigateOptions | NavigateOptions.BeyondEol);
				this.owner.OnStateChanged(this, NotifyState.SelectedTextChanged);
				Point point = this.IsEmpty ? source.Position : this.SelectionRect.Location;
				bool flag = !this.IsEmpty && source.Position.Equals(point);
				string text2 = source.Lines[point.Y];
				bool flag2 = !text.Contains("\r\n") && text.EndsWith('\r'.ToString());
				int num = text2.Length;
				if (point.X > num && !source.Lines.UseSpaces)
				{
					point.X = num + source.Lines.GetIndentString(point.X - num, source.Lines.TabPosToPos(text2, num)).Length;
				}
				if (this.Delete())
				{
					if (text != string.Empty && text != null)
					{
						if (selType == SelectionType.Stream)
						{
							Point position = source.Position;
							if (flag2)
							{
								text = text.Replace('\r'.ToString(), "\r\n");
								source.Position = new Point(0, source.Position.Y);
							}
							try
							{
								source.InsertBlock(text);
							}
							finally
							{
								if (flag2)
								{
									source.Position = position;
								}
							}
							this.SetSelection(SelectionType.Stream, point, this.owner.Position);
							if (flag && !moveToEnd)
							{
								this.owner.Position = point;
							}
						}
						else
						{
							source.Position = point;
							source.BeginUpdate(UpdateReason.Insert);
							try
							{
								string[] array = StringItem.Split(text);
								num = 0;
								for (int i = 0; i < array.Length; i++)
								{
									if (i > 0 && selType == SelectionType.Block)
									{
										source.Navigate(-num, 0);
									}
									num = this.DoInsertString(selType, array[i], i != 0);
								}
								this.SetSelection(selType, point, this.owner.Position);
								if (flag)
								{
									this.owner.Position = point;
								}
							}
							finally
							{
								this.owner.Source.EndUpdate();
							}
						}
					}
					this.selStart = new Point(this.selectionRect.Left, this.selectionRect.Top);
					this.selEnd = new Point(this.selectionRect.Right, this.selectionRect.Bottom);
				}
			}
			finally
			{
				source.SetNavigateOptions(navigateOptions);
				source.EndUpdate();
				this.EndUpdate();
			}
		}
		public string SelectedData(int index)
		{
			string result;
			if (this.IsEmpty)
			{
				result = null;
			}
			else
			{
				int top = this.selectionRect.Top;
				IList<Range> list = new List<Range>();
				this.GetSelectedBounds(index + top, list);
				if (list.Count == 0)
				{
					result = null;
				}
				else
				{
					switch (this.SelectionType)
					{
					case SelectionType.Stream:
					{
						Range range = list[0];
						StringItem item = this.owner.Lines.GetItem(range.StartPoint.Y);
						result = ((item != null) ? this.SafeSubString(item.TextData, range.StartPoint.X, range.EndPoint.X) : string.Empty);
						break;
					}
					case SelectionType.Block:
					{
						StringBuilder stringBuilder = new StringBuilder();
						for (int i = 0; i < list.Count; i++)
						{
							Range range = list[i];
							StringItem item = this.owner.Lines.GetItem(range.StartPoint.Y);
							if (item != null)
							{
								stringBuilder.Append(this.SafeSubString(item.TextData, range.StartPoint.X, range.EndPoint.X));
							}
							if (i != list.Count - 1)
							{
								stringBuilder.Append(new string('\0', this.owner.LineTerminator.Length));
							}
						}
						result = stringBuilder.ToString();
						break;
					}
					default:
						result = null;
						break;
					}
				}
			}
			return result;
		}
	
		protected virtual void Dispose(bool disposing)
		{
			if (disposing)
			{
				if (this.selTimer != null)
				{
					this.selTimer.Dispose();
					this.selTimer = null;
				}
			}
		}
		public void Dispose()
		{
			this.Dispose(true);
			GC.SuppressFinalize(this);
		}
	}
}
